package by.cooker.chat.logic;

import static by.cooker.chat.logic.MessageConstants.*;

import java.awt.Color;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;
import java.util.concurrent.LinkedBlockingQueue;

import javax.swing.DefaultListModel;
import javax.swing.JList;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;

import by.cooker.chat.gui.MessagesArea;
import by.cooker.chat.gui.Window;

/**
 * @author cooker
 */
public class Printer implements Runnable
{
	private DefaultListModel defaultModel;

	private SimpleAttributeSet emoteMsgSet;

	private SimpleAttributeSet errorMsgSet;

	private SimpleAttributeSet infoMsgSet;

	private MessagesArea messagesArea;

	private LinkedBlockingQueue<String> messagesQueue;

	private SimpleAttributeSet nameMsgSet;

	private SimpleAttributeSet textMsgSet;

	private Properties themeProps;

	private JList usersList;

	private SimpleAttributeSet whisperMsgSet;

	private Window window;

	/**
	 * @param win
	 *            owner
	 * @param messages
	 *            queue for text message
	 */
	public Printer(Window window, LinkedBlockingQueue<String> messagesQueue)
	{
		this.window = window;
		this.messagesQueue = messagesQueue;
		initialize();
	}

	/**
	 * Add user to users list.
	 * 
	 * @param name
	 *            the user name.
	 */
	public void addUser(String name)
	{
		if (!isExist(name))
		{
			defaultModel.addElement(String.valueOf(name));
		}
	}

	/**
	 * Method return client type.
	 * 
	 * @param client
	 *            client name for detect.
	 * @return client type.
	 */
	protected String getClientType(String client)
	{
		if ("[D2XP]".equals(client))
		{
			return " [d2xp]";
		}
		return " [chat]";
	}

	public SimpleAttributeSet getEmoteMsgSet()
	{
		if (emoteMsgSet == null)
		{
			emoteMsgSet = new SimpleAttributeSet();
			StyleConstants.setForeground(emoteMsgSet, Color
					.decode(getThemeProperties().getProperty("emote")));
		}
		return emoteMsgSet;
	}

	public SimpleAttributeSet getErrorMsgSet()
	{
		if (errorMsgSet == null)
		{
			errorMsgSet = new SimpleAttributeSet();
			StyleConstants.setForeground(errorMsgSet, Color
					.decode(getThemeProperties().getProperty("error")));
		}
		return errorMsgSet;
	}

	public SimpleAttributeSet getInfoMsgSet()
	{
		if (infoMsgSet == null)
		{
			infoMsgSet = new SimpleAttributeSet();
			StyleConstants.setForeground(infoMsgSet, Color
					.decode(getThemeProperties().getProperty("info")));
		}
		return infoMsgSet;
	}

	public SimpleAttributeSet getNameMsgSet()
	{
		if (nameMsgSet == null)
		{
			nameMsgSet = new SimpleAttributeSet();
			StyleConstants.setForeground(nameMsgSet, Color
					.decode(getThemeProperties().getProperty("user")));
		}
		return nameMsgSet;
	}

	public SimpleAttributeSet getTextMsgSet()
	{
		if (textMsgSet == null)
		{
			textMsgSet = new SimpleAttributeSet();
			StyleConstants.setForeground(textMsgSet, Color
					.decode(getThemeProperties().getProperty("text")));
		}
		return textMsgSet;
	}

	/**
	 * Get properties.
	 * 
	 * @return properties.
	 */
	public Properties getThemeProperties()
	{
		if (themeProps == null)
		{
			themeProps = new Properties();
			try
			{
				FileInputStream stream = new FileInputStream(new File(
						Configuration.getConf().getString("theme.file")));
				themeProps.load(stream);
				stream.close();
			} catch (FileNotFoundException e)
			{
				e.printStackTrace();
			} catch (IOException e)
			{
				e.printStackTrace();
			}
		}
		return themeProps;
	}

	public SimpleAttributeSet getWhisperMsgSet()
	{
		if (whisperMsgSet == null)
		{
			whisperMsgSet = new SimpleAttributeSet();
			StyleConstants.setForeground(whisperMsgSet, Color
					.decode(getThemeProperties().getProperty("whisper")));
		}
		return whisperMsgSet;
	}

	/**
	 * Initialize.
	 */
	private void initialize()
	{
		messagesArea = window.getMessagesArea();
		usersList = window.getUsersList();

		defaultModel = new DefaultListModel();

		usersList.setModel(defaultModel);

	}

	/**
	 * Check user.
	 * 
	 * @return <b>true</b> if user exist and <b>false</b> if not exist.
	 */
	public boolean isExist(String name)
	{
		for (int ix = 0; ix < defaultModel.getSize(); ix++)
		{
			if (defaultModel.get(ix).equals(name))
			{
				return true;
			}
		}
		return false;
	}

	/**
	 * Method parse and print message.
	 * 
	 * @param message
	 *            the message
	 */
	public void printMsg(String message)
	{
		int code = 0;
		String[] data = message.split(" ");
		try
		{
			code = Integer.parseInt(data[0]);
		} catch (NumberFormatException e)
		{
			messagesArea.appendText(message, getErrorMsgSet());
		}
		StringBuilder sb = new StringBuilder();
		switch (code)
		{

		case USER:
			addUser(data[2]);
			break;

		case JOIN:
			addUser(data[2]);
			break;

		case LEAVE:
			removeUser(data[2]);
			break;

		case INFO:
			sb.append(message.substring(10, message.length()).replace("\"", ""));
			sb.append("\n");
			messagesArea.appendText(sb.toString(), getInfoMsgSet());
			break;

		case CHANNEL:
			String line = message.substring(message.indexOf("\""), message.length());
			sb.append("Yout joining in channel ");
			sb.append(line);
			sb.append("\n");
			messagesArea.appendText(sb.toString(), getInfoMsgSet());
			sb.setLength(0);
			
			removeAllUsers();
			break;

		case WHISPER:
			sb.append("(");
			sb.append(Formater.getTime());
			sb.append(") ");
			sb.append("{FROM: ");
			sb.append(data[2]);
			sb.append("}: ");
			sb.append(message.substring(13 + data[2].toString().length() + 5)
					.replace("\"", ""));
			sb.append("\n");
			messagesArea.appendText(sb.toString(), getWhisperMsgSet());
			sb.setLength(0);
			break;

		case EMOTE:
			sb.append("(" + Formater.getTime() + ") ");
			sb.append("***");
			sb.append(data[2]);
			sb.append(message.substring(11 + data[2].toString().length() + 5)
					.replace("\"", ""));
			sb.append("\n");
			messagesArea.appendText(sb.toString(), getEmoteMsgSet());
			sb.setLength(0);
			break;

		case TALK:
			sb.append("(");
			sb.append(Formater.getTime());
			sb.append(") ");
			sb.append(data[2]);
			sb.append(": ");
			messagesArea.appendText(sb.toString(), getNameMsgSet());
			sb.setLength(0);
			sb.append(message.substring(10 + data[2].toString().length() + 5)
					.replace("\"", ""));
			sb.append("\n");
			messagesArea.appendText(sb.toString(), getTextMsgSet());
			sb.setLength(0);
			break;

		case ERROR:
			sb
					.append(message.substring(10, message.length()).replace(
							"\"", ""));
			sb.append("\n");
			messagesArea.appendText(sb.toString(), getErrorMsgSet());
			sb.setLength(0);
			break;

		case MY_WHISPER:
			sb.append("(");
			sb.append(Formater.getTime());
			sb.append(") ");
			sb.append("{TO: ");
			sb.append(data[2]);
			sb.append("}: ");
			sb.append(message.substring(13 + data[2].toString().length() + 5)
					.replace("\"", ""));
			sb.append("\n");
			messagesArea.appendText(sb.toString(), getWhisperMsgSet());
			sb.setLength(0);
			break;
		default:
			break;
		}
	}

	/**
	 * Remove all users.
	 */
	public void removeAllUsers()
	{
		defaultModel.removeAllElements();
	}

	/**
	 * Remove user by name.
	 * 
	 * @param name
	 *            user name
	 */
	public void removeUser(String name)
	{
		defaultModel.remove(defaultModel.indexOf(name));
	}

	@Override
	public void run()
	{
		while (true)
		{
			try
			{
				printMsg(messagesQueue.take());
			} catch (InterruptedException ex)
			{
				ex.printStackTrace();
			}
		}
	}
}